/*-
 * MatchOptions.java
 *
 * $LastChangedBy: stein $
 * $LastChangedRevision: 95 $
 * $LastChangedDate: 2007-02-13 16:19:24 +0000 (Tue, 13 Feb 2007) $
 * $HeadURL: svn://localhost/SMS/src/com/googlecode/attention/sms/comp/MatchOptions.java $
 *
 * Copyright (c) 2007, Stein Gunnar Bakkeby
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Stein Gunnar Bakkeby nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.googlecode.attention.sms.comp;

import com.googlecode.attention.util.Convert;
import com.googlecode.attention.util.IntArrayBuilder;

/**
 * This class represents match options.
 *
 * @author Stein Gunnar Bakkeby
 */
public class MatchOptions {
  /* Field values */
  private int[]  reservedBits;
  private boolean exactMatch;
  private boolean lowerMatch;
  private boolean upperMatch;
  private boolean upper1stMatch;
  private boolean prefixMatch;
  private boolean suffixMatch;
  private boolean partialMatch;
  
  /**
   * Constructor, based on a binary string.
   * 
   * @param bitstream The binary string with length >= 7
   * @throws IllegalArgumentException If length < 7
   */
  public MatchOptions(int[] bitstream) {
    if (bitstream.length < 7)
        throw new IllegalArgumentException(bitstream.toString());
    int length = bitstream.length - 7;
    reservedBits  = new int[length];
    System.arraycopy(bitstream, 0, reservedBits, 0, length);
    System.arraycopy(bitstream, length, bitstream, 0, 7);
    exactMatch    = bitstream[6] == 1;
    lowerMatch    = bitstream[5] == 1;
    upperMatch    = bitstream[4] == 1;
    upper1stMatch = bitstream[3] == 1;
    prefixMatch   = bitstream[2] == 1;
    suffixMatch   = bitstream[1] == 1;
    partialMatch  = bitstream[0] == 1;
    /* All other values reserved. */
  }
  
  /**
   * Constructor, converts the String bitstream into int[] bitstream.
   * 
   * @param bitstream The bitstream
   * @see #MatchOptions(int[])
   */
  public MatchOptions(final String bitstream) {
    this(Convert.stringToInt(bitstream));
  }
  
  /**
   * Default constructor, creates match options
   * indicating exact match enabled.
   */
  public MatchOptions() {
    this(new int[] {0, 0, 0, 0, 0, 0, 1});
  }
  
  /**
   * This will return true if exact matching is enabled.
   * 
   * @return True if enabled, false otherwise
   */
  public boolean isExactMatchEnabled() {
    return exactMatch;
  }
  
  /**
   * If this is set to true, then exact matching will be enabled and
   * any case related matching will be disabled.
   * 
   * @param value True if enabled, false otherwise
   */
  public void setExactMatchEnabled(final boolean value) {
    exactMatch = value;
    if (value) {
      lowerMatch    = false;
      upperMatch    = false;
      upper1stMatch = false;
    }
  }
  
  /**
   * This will return true if lower case matching is enabled.
   * 
   * @return True if enabled, false otherwise
   */
  public boolean isLowerMatchEnabled() {
    return lowerMatch;
  }
  
  /**
   * If this is set to true, then lower case matching will be enabled
   * and exact matching will be disabled.
   * 
   * @param value True if enabled, false otherwise
   */
  public void setLowerMatchEnabled(final boolean value) {
    lowerMatch = value;
    if (value) exactMatch = false;
  }
  
  /**
   * This will return true if lower case matching is enabled.
   * 
   * @return True if enabled, false otherwise
   */
  public boolean isUpperMatchEnabled() {
    return upperMatch;
  }
  
  /**
   * If this is set to true then upper case matching will be enabled
   * and exact matching will be disabled.
   * 
   * @param value True if enabled, false otherwise
   */
  public void setUpperMatchEnabled(final boolean value) {
    upperMatch = value;
    if (value) exactMatch = false;
  }
  
  /**
   * This will return true if upper case 1st remainder lower case matching
   * is enabled.
   * 
   * @return True if enabled, false otherwise
   */
  public boolean isUpper1stMatchEnabled() {
    return upper1stMatch;
  }
  
  /**
   * If this is set to true then upper case 1st remainder lower case matching
   * will be enabled and exact matching will be disabled.
   * 
   * @param value True if enabled, false otherwise
   */
  public void setUpper1stMatchEnabled(final boolean value) {
    upper1stMatch = value;
    if (value) exactMatch = false;
  }
  
  /**
   * This will return true if partial matching is enabled.
   * 
   * @return True if enabled, false otherwise
   */
  public boolean isPartialMatchEnabled() {
    return partialMatch;
  }
  
  /**
   * This will set partial matching enabled or disabled.
   * 
   * @param value True if enabled, false otherwise
   */
  public void setPartialMatchEnabled(final boolean value) {
    partialMatch = value;
  }
  
  /**
   * This will return true if prefix matching is enabled.
   * 
   * @return True if enabled, false otherwise
   */
  public boolean isPrefixMatchEnabled() {
    return prefixMatch;
  }
  
  /**
   * This will set prefix matching enabled or disabled.
   * 
   * @param value True if enabled, false otherwise
   */
  public void setPrefixMatchEnabled(final boolean value) {
    prefixMatch = value;
  }
  
  /**
   * This will return true if suffix matching is enabled.
   * 
   * @return True if enabled, false otherwise
   */
  public boolean isSuffixMatchEnabled() {
    return suffixMatch;
  }
  
  /**
   * This will set suffix matching enabled or disabled.
   * 
   * @param value True if enabled, false otherwise
   */
  public void setSuffixMatchEnabled(final boolean value) {
    suffixMatch = value;
  }

  /**
   * This will return the reserved bits.
   * 
   * @return The reserved bits, if any
   */
  public int[] getReservedBits() {
    return reservedBits;
  }

  /**
   * This will set the reserved bits.
   * 
   * @param bits
   */
  public void setReservedBits(final int[] bits) {
    this.reservedBits = bits;
  }

  /**
   * This will return the binary string representing the match options.
   * 
   * @return A binary string
   */
  public int[] getBitstream() {
    IntArrayBuilder output = new IntArrayBuilder(reservedBits.length + 7);
    output.append(reservedBits);
    output.append(partialMatch);
    output.append(suffixMatch);
    output.append(prefixMatch);
    output.append(upper1stMatch);
    output.append(upperMatch);
    output.append(lowerMatch);
    output.append(exactMatch);
    return output.toArray();
  }
}